﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace System.Windows.Media.DirectShow.Filters
{
    internal class WaveSourceParserOutputPin : BasePullPin
    {

        private WaveSourceParser filter;
        private AMMediaType[] _mediaTypes;
        private WaveFormatExtensible format;

        public WaveSourceParserOutputPin(WaveSourceParser filter, AMMediaType mediaType)
            : base(filter)
        {
            this.filter = filter;
            this.format = (WaveFormatExtensible)mediaType.Format;
            this._mediaTypes = new AMMediaType[] { mediaType };
        }

        public override System.Collections.Generic.IEnumerable<AMMediaType> MediaTypes
        {
            get { return _mediaTypes; }
        }

        public override string Name
        {
            get { return "Wave out"; }
        }

        protected override void Request(long startMediaTime, long endMediaTime, object state)
        {
            if (startMediaTime == 0 && endMediaTime == 0)
            {
                startMediaTime = WaveSourceParser.HeaderSize;
                endMediaTime = startMediaTime + this.Allocator.Properties.BufferSize;
            }
            else
            {
                startMediaTime += WaveSourceParser.HeaderSize;
                endMediaTime += WaveSourceParser.HeaderSize;
            }

            // Ensure isn't reach the end
            if (endMediaTime > this.filter.BaseStream.Length)
                endMediaTime = this.filter.BaseStream.Length;

            // Set stream position
            this.filter.BaseStream.Seek(startMediaTime, SeekOrigin.Begin);

            TimeSpan start = TimeSpan.FromSeconds((startMediaTime - WaveSourceParser.HeaderSize) / (double)format.AverageBytesPerSecond);
            TimeSpan end = TimeSpan.FromSeconds((endMediaTime - WaveSourceParser.HeaderSize) / (double)format.AverageBytesPerSecond);

            //Debug.WriteLine("{0} {1}", start, end);
            IMediaSample sample = this.Allocator.GetBuffer(start, end);
            if (sample == null) return;
            sample.AddRef();
            try
            {
                sample.StartMediaTime = startMediaTime - WaveSourceParser.HeaderSize;
                sample.EndMediaTime = endMediaTime - WaveSourceParser.HeaderSize;
                sample.StartTime = start;
                sample.EndTime = end;
                sample.MediaType = this._mediaTypes[0];
                sample.Length = this.filter.BaseStream.Read(sample.Data, 0, (int)(endMediaTime - startMediaTime));

                if (sample.Length > 0)
                    this.DeliverAsync(sample);
                else
                    this.DeliverEndOfStream();
            }
            finally
            {
                sample.Release();
            }
        }
    }
}
